package com.snopy.logistics.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author snopy
 * @version 1.0.0
 * @classname MTControler
 * @description
 * @email 77912204@qq.com
 * @date 2022/06/23 8:20
 */
@Slf4j
@RestController
@RequestMapping("mt")
public class MTControler {
    static int num = 0;
    static AtomicInteger n = new AtomicInteger(0);
    final Lock lock = new ReentrantLock();
    Map<String,Thread> map = new HashMap<>();
    static boolean starting = false;
    int number = 0;
    boolean ready = false;
    @PostMapping("/actor1")
    public int actor1(){
        int result = 0;
        if (ready){
            result = number+number;
        }else {
            result = 1;
        }
        return result;
    }
    @PostMapping("/actor2")
    public void actor2(){
        number = 2;
        ready = true;
    }
    @PostMapping("/atomicOperat")
    public synchronized int atomicOperat(){

        if (!starting){
            n.getAndIncrement();
        }
        starting = true;
        log.info("num:{}",n.get());
        return n.get();
    }
    @PostMapping("/reset")
    public void reset(){
        starting = false;
        n.set(0);
    }
    @PostMapping("/output")
    public void output(){
        map.put("output",Thread.currentThread());
        try {
            if (lock.tryLock(3,TimeUnit.SECONDS)){
                log.info("获取锁失败...");
                return;
            }
        } catch (InterruptedException e) {
            log.info("try-lock interrupt...");
            e.printStackTrace();
            return;
        }
        try {
            log.info("get lock ...");
        }finally {
            lock.unlock();
        }

    }
    @PostMapping("/interrupt")
    public void interrupt(){
        /*try {*/
            log.info("try to get lock...");
            map.put("interrupt",Thread.currentThread());
            //lock.lockInterruptibly();
            lock.lock();
            log.info("get lock...");
       /* } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        try {
            log.info("task...");
        }finally {
            lock.unlock();
        }
    }

    @PostMapping("/reEntry")
    public void reEntry(){
        lock.lock();
        try {
            log.info("entry first...");
            try {
                TimeUnit.SECONDS.sleep(2);
                log.info("打断 interrupt()...");
                map.get("output").interrupt();
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //entryAgain();
        }finally {
            lock.unlock();
        }
    }
    private void entryAgain(){
        lock.lock();
        try {
            log.info("entry second...");
            entryDoubleAgain();
        }finally {
            lock.unlock();
        }
    }
    private void entryDoubleAgain(){
        lock.lock();
        try {
            log.info("entry 3td...");
        }finally {
            lock.unlock();
        }
    }
    @PostMapping("/add")
    public int add(int n) throws InterruptedException {
        //lock.lock();
        //log.info("add:{}",ClassLayout.parseInstance(lock).toPrintable());
        synchronized (lock){
          //  log.info("add class-layout:{}",ClassLayout.parseInstance(lock).toPrintable());
            num+=n;
            if (num>20000){
                TimeUnit.SECONDS.sleep(4);
                lock.notifyAll();
            }
        }
        //int result = method(n);

        //lock.unlock();
        return num;
    }
    @PostMapping("/sub")
    public int sub(int n){
        //lock.lock();
        //for (int i = 0; i < 40; i++) {
            synchronized (lock) {
                //log.info("sub:{},class-layout:{}",i, ClassLayout.parseInstance(lock).toPrintable());
                num -= n;
            }
       // }
        //log.info("sub:{}",ClassLayout.parseInstance(lock).toPrintable());
        //lock.unlock();
        return num;
    }
    private int method(int num){
        int result = 10,x=2;
        synchronized (lock){
            num = (num+result)%2;
        }
        return num;
    }
    @PostMapping("/eat")
    public String eat(String food){
        log.info(" eat thread state:{}",Thread.currentThread().getState());
        synchronized (lock){
            if (num<20000){
                try {
                    log.info(" eat thread state:{}",Thread.currentThread().getState());
                    lock.wait();
                    log.info(" eat thread state:{}",Thread.currentThread().getState());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            switch (food){
                case "春": food = "清炒大白菜";
                break;
                case "夏": food = "冰镇西瓜";
                break;
                case "秋": food = "青红丝月饼";
                break;
                case "冬": food = "满汉全席";
                break;
                default:
                    break;
            }
            log.info("钱到位，开吃...{}",food);
        }
        return food;
    }
}
